package pe.com.bbva.modpre.negocio.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.vaadin.ui.Window;

import pe.com.bbva.modpre.dominio.Membresia;
import pe.com.bbva.modpre.dominio.Opcion;
import pe.com.bbva.modpre.dominio.Permiso;
import pe.com.bbva.modpre.dominio.Preferencia;
import pe.com.bbva.modpre.dominio.Rol;
import pe.com.bbva.modpre.dominio.RolTipoBanca;
import pe.com.bbva.modpre.dominio.TipoBanca;
import pe.com.bbva.modpre.dominio.Usuario;
import pe.com.bbva.modpre.dominio.Valor;
import pe.com.bbva.modpre.dominioLDAP.Ldapperu2;
import pe.com.bbva.modpre.exception.ValidacionException;
import pe.com.bbva.modpre.negocio.SeguridadService;
import pe.com.bbva.modpre.persistencia.EquipoDAO;
import pe.com.bbva.modpre.persistencia.LDAP2DAO;
import pe.com.bbva.modpre.persistencia.MembresiaDAO;
import pe.com.bbva.modpre.persistencia.OpcionDAO;
import pe.com.bbva.modpre.persistencia.PermisoDAO;
import pe.com.bbva.modpre.persistencia.PreferenciaDAO;
import pe.com.bbva.modpre.persistencia.RolDAO;
import pe.com.bbva.modpre.persistencia.RolTipoBancaDAO;
import pe.com.bbva.modpre.persistencia.TipoBancaDAO;
import pe.com.bbva.modpre.persistencia.UsuarioDAO;
import pe.com.bbva.modpre.utileria.Constante;
import pe.com.bbva.modpre.utileria.ModpreUtil;

@Service
@SuppressWarnings("serial")
public class SeguridadServiceImpl extends ConfiguracionServiceImpl implements SeguridadService{

	@Autowired
	private UsuarioDAO usuarioDAO;
	@Autowired
	private LDAP2DAO ldap2DAO;
	@Autowired
	private OpcionDAO opcionDAO;
	@Autowired
	private EquipoDAO equipoDAO;
	@Autowired
	private RolDAO rolDAO;
	@Autowired
	private MembresiaDAO membresiaDAO;
	@Autowired
	private RolTipoBancaDAO rolTipoBancaDAO;
	
	@Autowired
	private TipoBancaDAO tipoBancaDAO;
	@Autowired
	private PermisoDAO permisoDAO;
	@Autowired
	private PreferenciaDAO preferenciaDAO;
	
	@Override
	public Usuario login(String loginUsuario, String password, Window window) {
		boolean error=ldap2DAO.autenticacionLDAP(loginUsuario, password, window);
		if(error){
			return null;
		}
		Usuario usuarioLDAP=ldap2DAO.login(loginUsuario, window);
		if(usuarioLDAP!=null){
			Usuario usuario=usuarioDAO.obtenerUsuarioxRegistro(usuarioLDAP.getRegistro());
			if(usuario==null){
				usuarioDAO.crear(usuarioLDAP);
				usuario=usuarioLDAP;
			}else{
				usuario.setNombres(usuarioLDAP.getNombres());
				usuario.setPaterno(usuarioLDAP.getPaterno());
				usuario.setMaterno(usuarioLDAP.getMaterno());
				usuario.setRegistro(loginUsuario);
				usuario.setCargo(usuarioLDAP.getCargo());
				usuario.setDescCargo(usuarioLDAP.getDescCargo());
				usuario.setCorreo(usuarioLDAP.getCorreo());
				usuario.setOficina(usuarioLDAP.getOficina());
				usuario.setDescOficina(usuarioLDAP.getDescOficina());
				usuarioDAO.actualizar(usuario);
			}
			usuario.setRol(rolDAO.obtenerRolxMembresia(usuario.getRegistro()));
			usuario.setEquipo(equipoDAO.obtenerEquipoxUsuario(usuario));
			return usuario;
		}
		return null;
	}

	@Override
	public Usuario login(String loginUsuario, Window window) {
		Usuario usuarioLDAP=ldap2DAO.login(loginUsuario, window);
		if(usuarioLDAP!=null){
			Usuario usuario=usuarioDAO.obtenerUsuarioxRegistro(usuarioLDAP.getRegistro());
			if(usuario==null){
				usuarioDAO.crear(usuarioLDAP);
				usuario=usuarioLDAP;
			}else{
				usuario.setNombres(usuarioLDAP.getNombres());
				usuario.setPaterno(usuarioLDAP.getPaterno());
				usuario.setMaterno(usuarioLDAP.getMaterno());
				usuario.setRegistro(loginUsuario);
				usuario.setCargo(usuarioLDAP.getCargo());
				usuario.setDescCargo(usuarioLDAP.getDescCargo());
				usuario.setCorreo(usuarioLDAP.getCorreo());
				usuario.setOficina(usuarioLDAP.getOficina());
				usuario.setDescOficina(usuarioLDAP.getDescOficina());
				usuarioDAO.actualizar(usuario);
			}
			usuario.setRol(rolDAO.obtenerRolxMembresia(usuario.getRegistro()));
			usuario.setEquipo(equipoDAO.obtenerEquipoxUsuario(usuario));
			return usuario;
		}
		return null;
	}

	@Override
	public Map<String, List<Opcion>> obtenerOpciones() {
		Usuario usuario=ModpreUtil.obtenerUsuarioSesion();
		Map<String, List<Opcion>> map=new HashMap<String, List<Opcion>>();
		if(usuario!=null){
			Membresia membresia=membresiaDAO.obtenerMembresiaxUsuario(usuario.getRegistro());
			if(membresia!=null){
				List<Opcion> opciones=opcionDAO.obtenerOpcionesxRol(membresia.getRol());
				map=ModpreUtil.ordenarOpciones(opciones);
			}
		}
		return map;
	}

	@Override
	public List<Rol> buscarRoles(Rol rol) {
		return rolDAO.busquedaRoles(rol);
	}

	@Override
	public List<Membresia> buscarMembresia(Membresia membresia) {
		return membresiaDAO.busquedaMembresia(membresia);
	}

	@Override
	public List<RolTipoBanca> obtenerRolBancas(Rol rol) {
		return rolTipoBancaDAO.buscarTipoBancaxRol(rol);
	}

	@Override
	public void guardarRol(Rol rol) {
		if(rol.getId()==null){
			rolDAO.crear(rol);
		}else{
			rolDAO.actualizar(rol);
		}
	}

	@Override
	public void eliminarRol(Long id) {
		try {
			rolDAO.eliminarXId(id);
		} catch (Exception e) {
			throw new ValidacionException(Constante.CODIGO_MENSAJE.VALIDAR_ELIMINAR_REGISTRO,new Object[]{});
		}
	}

	@Override
	public void guardarMembresia(Membresia membresia) {
		if(membresia.getId()==null){
			membresiaDAO.crear(membresia);
		}else{
			membresiaDAO.actualizar(membresia);
		}
	}

	@Override
	public void eliminarMembresia(Long id) {
		membresiaDAO.eliminarXId(id);
	}

	@Override
	public List<TipoBanca> obtenerBancas() {
		return tipoBancaDAO.obtenerTodos();
	}

	@Override
	public void guardarRolTipoBanca(RolTipoBanca rolTipoBanca) {
		if(rolTipoBanca.getId()==null){
			rolTipoBancaDAO.crear(rolTipoBanca);
		}else{
			rolTipoBancaDAO.actualizar(rolTipoBanca);
		}
		
	}

	@Override
	public void eliminarRolTipoBanca(Long id) {
		rolTipoBancaDAO.eliminarXId(id);
	}
	
	@Override
    public List<Permiso> obtenerPermisosXRol(Long idRol, boolean estadoActivo){
            return permisoDAO.obtenerPermisosXRol(idRol, estadoActivo);
    }
	 @Override
     public Map<String, List<Opcion>> listarOpciones() {
             return opcionDAO.listarOpciones();
     }
	 
	 @SuppressWarnings("unchecked")
     @Override
     public void guardarPermisos(Long idRol, List<Long> idsOpciones) {
             List<Permiso> permisosALL = obtenerPermisosXRol(idRol, false);
             List<Permiso> permisosA = obtenerPermisosXRol(idRol, true);
             List<Permiso> permisosSel = new ArrayList<Permiso>();
             for (Long idOpcion : idsOpciones) {
                     Permiso permiso = new Permiso();
                     permiso.setRol(new Rol());
                     permiso.getRol().setId(idRol);
                     permiso.setOpcion(new Opcion());
                     permiso.getOpcion().setId(idOpcion);
                     permisosSel.add(permiso);
             }
             List<Permiso> permisosD = ListUtils.subtract(permisosALL, permisosA);
             
             List<Permiso> updPermisosD = ListUtils.subtract(permisosA, permisosSel);
             List<Permiso> updPermisosA = ListUtils.intersection(permisosSel, permisosD);
             List<Permiso> insPermisosA = ListUtils.subtract(permisosSel, permisosALL);
             
             Valor estadoInactivo = obtenerValorxCodigo(Valor.CODIGO.INACTIVO);
             Valor estadoActivo = obtenerValorxCodigo(Valor.CODIGO.ACTIVO);
             
             prepararLista(updPermisosD, estadoInactivo);
             prepararLista(updPermisosA, estadoActivo);
             prepararLista(insPermisosA, estadoActivo);
             
             List<Permiso> permisosU = ListUtils.union(updPermisosD, updPermisosA);
             List<Permiso> permisos = ListUtils.union(permisosU, insPermisosA);
             
             permisoDAO.grabarTodos(permisos);
     }
	 
	 private void prepararLista(List<Permiso> lista, Valor estado)
     {
             for (Permiso permiso : lista) {
                     permiso.setEstado(estado);
             }
     }

	@Override
	public Usuario usuarioxRegistro(String registro) {
		return usuarioDAO.obtenerUsuarioxRegistro(registro);
	}

	@Override
	public boolean validarLdapUsuario(String registro) {
		Ldapperu2 usuarioLdap =ldap2DAO.obtener(registro);
		Usuario usuario=new Usuario();
		if(usuarioLdap!=null){
			usuario.setNombres(usuarioLdap.getNombre());
			usuario.setPaterno(usuarioLdap.getApepat());
			usuario.setMaterno(usuarioLdap.getApemat());
			usuario.setRegistro(usuarioLdap.getCodusu());
			usuario.setCargo(usuarioLdap.getCodcargo());
			usuario.setDescCargo(usuarioLdap.getNomcargo());
			usuario.setCorreo(usuarioLdap.getCorelec());
			usuario.setOficina(usuarioLdap.getCodofi());
			usuario.setDescOficina(usuarioLdap.getDesofi());
			
			if(usuarioDAO.obtenerUsuarioxRegistro(usuarioLdap.getCodusu())==null){
				usuarioDAO.crear(usuario);
			}else{
				usuario=usuarioDAO.obtenerUsuarioxRegistro(usuarioLdap.getCodusu());
				usuario.setNombres(usuarioLdap.getNombre());
				usuario.setPaterno(usuarioLdap.getApepat());
				usuario.setMaterno(usuarioLdap.getApemat());
				usuario.setRegistro(usuarioLdap.getCodusu());
				usuario.setCargo(usuarioLdap.getCodcargo());
				usuario.setDescCargo(usuarioLdap.getNomcargo());
				usuario.setCorreo(usuarioLdap.getCorelec());
				usuario.setOficina(usuarioLdap.getCodofi());
				usuario.setDescOficina(usuarioLdap.getDesofi());
				usuarioDAO.actualizar(usuario);
			}			
			return true;
		}
		return false;
	}

	@Override
	public Membresia membresiaxValor(String valor) {
		return membresiaDAO.obtenerMembresiaxUsuario(valor);
	}

	@Override
	public Preferencia obtenerPreferencia(Preferencia preferencia) {
		return preferenciaDAO.obtenerPreferencia(preferencia);
	}

	@Override
	public void guardarPreferencia(Preferencia preferencia) {
		if(preferencia.getId()==null){
			preferenciaDAO.crear(preferencia);
		}else{
			preferenciaDAO.actualizar(preferencia);
		}
	}
	 
	 

}
